﻿// **************************************************************************
// <copyright file="IMessenger.cs" company="GalaSoft Laurent Bugnion">
// Copyright © GalaSoft Laurent Bugnion 2009-2013
// </copyright>
// ****************************************************************************
// <author>Laurent Bugnion</author>
// <email>laurent@galasoft.ch</email>
// <date>23.9.2009</date>
// <project>GalaSoft.MvvmLight.Messaging</project>
// <web>http://www.galasoft.ch</web>
// <license>
// See license.txt in this project or http://www.galasoft.ch/license_MIT.txt
// </license>
// ****************************************************************************
using System;
using System.Diagnostics.CodeAnalysis;

namespace TimersXP.Messaging
{
    /// <summary>The IMessenger is an interface class allowing objects to exchange messages.</summary>
    public interface IMessenger
    {
        #region Register Functions
        /// <summary>
        /// Registers a recipient for a type of message TMessage. The action parameter will be executed when a corresponding message is sent.
        /// <para>Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.</para>
        /// </summary>
        /// <typeparam name="TMessage">The type of the message that the recipient registers for.</typeparam>
        /// <param name="recipient">The recipient that will receive the messages.</param>
        /// <param name="action">The action that will be executed when a message of type TMessage is sent.</param>
        void Register<TMessage>(object recipient, Action<TMessage> action);

        /// <summary>
        /// Registers a recipient for a type of message TMessage. The action parameter will be executed when a corresponding message is sent.
        /// See the receiveDerivedMessagesToo parameter for details on how messages deriving from TMessage (or, if TMessage is an interface, messages implementing TMessage)
        /// can be received too. <para>Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.</para>
        /// </summary>
        /// <typeparam name="TMessage">The type of message that the recipient registers for.</typeparam>
        /// <param name="recipient">The recipient that will receive the messages.</param>
        /// <param name="token">A token for a messaging channel. If a recipient registeres using a token, and a sender sends a message using the same token,
        /// then this message will be delivered to the recipient. Other recipients who did not use a token when registering (or who used a different token) will not get the message.
        /// Similarly, messages sent without any token, or with a different token, will not be delivered to that recipient.</param>
        /// <param name="action">The action that will be executed when a message of type TMessage is sent.</param>
        void Register<TMessage>(object recipient, object token, Action<TMessage> action);

        /// <summary>
        /// Registers a recipient for a type of message TMessage. The action parameter will be executed when a corresponding message is sent.
        /// See the receiveDerivedMessagesToo parameter for details on how messages deriving from TMessage (or, if TMessage is an interface, messages implementing TMessage)
        /// can be received too. <para>Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.</para>
        /// </summary>
        /// <typeparam name="TMessage">The type of message that the recipient registers for.</typeparam>
        /// <param name="recipient">The recipient that will receive the messages.</param>
        /// <param name="token">A token for a messaging channel. If a recipient registers using a token, and a sender sends a message using the same token,
        /// then this message will be delivered to the recipient. Other recipients who did not use a token when registering (or who used a different token)
        /// will not get the message. Similarly, messages sent without any token, or with a different token, will not be delivered to that recipient.</param>
        /// <param name="receiveDerivedMessagesToo">If set to <c>true</c> message types deriving from TMessage will also be transmitted to the recipient.
        /// For example, if a SendOrderMessage and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage and setting receiveDerivedMessagesToo to true
        /// will send SendOrderMessage and ExecuteOrderMessage to the recipient that registered.
        /// <para>Also, if TMessage is an interface, message types implementing TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage
        /// and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage and setting receiveDerivedMessagesToo to true will send SendOrderMessage
        /// and ExecuteOrderMessage to the recipient that registered.</para>.</param>
        /// <param name="action">The action that will be executed when a message of type TMessage is sent.</param>
        void Register<TMessage>(object recipient, object token, bool receiveDerivedMessagesToo, Action<TMessage> action);

        /// <summary>
        /// Registers a recipient for a type of message TMessage. The action parameter will be executed when a corresponding message is sent.
        /// See the receiveDerivedMessagesToo parameter for details on how messages deriving from TMessage (or, if TMessage is an interface,
        /// messages implementing TMessage) can be received too.
        /// <para>Registering a recipient does not create a hard reference to it, so if this recipient is deleted, no memory leak is caused.</para>
        /// </summary>
        /// <typeparam name="TMessage">The type of message that the recipient registers for.</typeparam>
        /// <param name="recipient">The recipient that will receive the messages.</param>
        /// <param name="receiverDerivedMessagesToo">If true, message types deriving from TMessage will also be transmitted to the recipient.
        /// For example, if a SendOrderMessage and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage and setting
        /// receiveDerivedMessagesToo to true will send SendOrderMessage and ExecuteOrderMessage to the recipient that registered.
        /// <para>Also, if TMessage is an interface, message types implementing TMessage will also be transmitted to the recipient.
        /// For example, if a SendOrderMessage and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage
        /// and setting receiveDerivedMessagesToo to true will send SendOrderMessage and ExecuteOrderMessage to the recipient that registered.</para>
        /// </param>
        /// <param name="action">The action that will be executed when a message of type TMessage is sent.</param>
        void Register<TMessage>(object recipient, bool receiverDerivedMessagesToo, Action<TMessage> action);
        #endregion Register Functions

        #region Send Functions
        /// <summary>
        /// Sends a message to the registered recipients.
        /// The message will reach all recipients that registered for this message type using one of the Register methods.
        /// </summary>
        /// <typeparam name="TMessage">The type of the message that will be sent.</typeparam>
        /// <param name="message">The message to send to registered recipients.</param>
        void Send<TMessage>(TMessage message);

        /// <summary>
        /// Sends a message to registered recipients. The message will reach only recipients that registered for this message type
        /// using one of the Register methods, and that are of the targetType.
        /// </summary>
        /// <typeparam name="TMessage">The type of message that will be sent.</typeparam>
        /// <typeparam name="TTarget">The type of recipients that will receive the message. The message won't be sent to recipients of another type.</typeparam>
        /// <param name="message">The message to send to registered recipients.</param>
        /// <NOTE>
        /// SuppressMessage is used by System.Diagnostics.CodeAnalysis. When you are applying code analysis to your project you will sometimes
        /// get warnings that you want to ignore. You do that by using SuprpressMessageAttribute. Now code analysis is built into the "higher" SKU's
        /// of Visual Studio but previously you had to use the tool named FxCop to prerform the analysis. Using code analysis on your code will not only
        /// increase the quality of your code but you might also learn a few things in the process.
        /// http://stackoverflow.com/questions/11910764/whats-the-use-of-supressmessage-attribute
        /// </NOTE>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This syntax is more convenient than other alternatives.")]
        void Send<TMessage, TTarget>(TMessage message);

        /// <summary>
        /// Sends a message to registered recipients. The message will reach only recipients that registered for this message type
        /// using one of the Register methods, and that are of the targetType.
        /// </summary>
        /// <typeparam name="TMessage">The type of the message that will be sent.</typeparam>
        /// <param name="message">The message to send to registered recipients.</param>
        /// <param name="token">A token for a messaging channel. If a recipient registers using a token, and a sender sends a message using the same token,
        /// then this message will be delivered to the recipient. Other recipients who did not use a token when registering (or who use a different token) will not get the message.
        /// Similarly, messages sent without any token, or with a different token, will not be delievered to that recipeint.</param>
        void Send<TMessage>(TMessage message, object token);
        #endregion Send Functions

        #region Unregister Functions
        /// <summary>Unregisters a messenger recipient completely. After this method is executed, the recipient will not receive any messages any more.</summary>
        /// <param name="recipient">The recipient that must be unregistered.</param>
        void Unregister(object recipient);
        
        /// <summary>
        /// Unregisters a message recipient for a given type of messages only. After this method is executed, the recipient will not receive messages
        /// of type TMessage anymore, but will still receive other message types (if it registered for them previously).
        /// </summary>
        /// <typeparam name="TMessage">The type of the messages that the recipient wants to unregister from.</typeparam>
        /// <param name="recipient">The recipient that must be unregistered.</param>
        /// /// <NOTE>
        /// SuppressMessage is used by System.Diagnostics.CodeAnalysis. When you are applying code analysis to your project you will sometimes
        /// get warnings that you want to ignore. You do that by using SuprpressMessageAttribute. Now code analysis is built into the "higher" SKU's
        /// of Visual Studio but previously you had to use the tool named FxCop to prerform the analysis. Using code analysis on your code will not only
        /// increase the quality of your code but you might also learn a few things in the process.
        /// http://stackoverflow.com/questions/11910764/whats-the-use-of-supressmessage-attribute
        /// </NOTE>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This syntax is more convenient than other alternatives.")]
        void Unregister<TMessage>(object recipient);

        /// <summary>
        /// Unregisters a recipient for a given type of messages only and for a given token. After this method is executed, the recipient will not receive messages
        /// of type TMessage anymore with the given token, but will still receive other message types or messages with other tokens (if it registered for them previously).
        /// </summary>
        /// <typeparam name="TMessage">The type of messages that the recipient wants to unregister from.</typeparam>
        /// <param name="recipient">The recipient that must be unregistered.</param>
        /// <param name="token">The token for which the recipient must be unregistered.</param>
        [SuppressMessage(
            "Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This syntax is more convenient than other alternatives.")]
        void Unregister<TMessage>(object recipient, object token);

        /// <summary>
        /// Unregisters a message recipient for a given type of messages and for a given action. Other message types will still be transmitted
        /// to the recipient (if it registered for them previously). Other actions that have been registered for the message type TMessage and
        /// for the given recipient (if available) will also remain available.
        /// </summary>
        /// <typeparam name="TMessage">The type messages that the recipient wants to unregister from.</typeparam>
        /// <param name="recipient">The recipient that must be unregistered.</param>
        /// <param name="action">The action that must be unregistered for the recipient and for the message type TMessage.</param>
        void Unregister<TMessage>(object recipient, Action<TMessage> action);

        /// <summary>
        /// Unregisters a message recipient for a given type of messages, for a given action and a given token. Other message types will still be transmitted
        /// to the recipient (if it registered for them previously). Other actions that have been registered for the message type TMessage, for the given recipient and other tokens
        /// (if available) will also remain available.
        /// </summary>
        /// <typeparam name="TMessage">The type of messages that the recipient wants to unregister from.</typeparam>
        /// <param name="recipient">The recipient that must be unregistered.</param>
        /// <param name="token">The token for which the recipient must be unregistered.</param>
        /// <param name="action">The action that must be unregistered for the recipient and for the message type TMessage.</param>
        void Unregister<TMessage>(object recipient, object token, Action<TMessage> action);
        #endregion Unregister Functions
    }
}
